/*
*	Copyright (C) 2014  Julio Montes, Mario Carrillo
*
*	Julio Montes e-mail: imc.coder@gmail.com
*
*	Mario Carrillo e-mail: mario_90ago@live.com.mx
*
*	BSD 3-Clause License
*/

#include "sdk/include/editor.h"
#include "sdk/include/editormgr.h"
#include "sdk/include/cfgmgr.h"
#include "include/iaManager.h"
#include "sdk/include/filecfg.h"
#include "sdk/include/lexermgr.h"
#include "sdk/include/lexer.h"
#include "sdk/include/notebookeditor.h"
#include "sdk/include/mainframe.h"

namespace sdk
{
    template<> EditorManager *sdk::Mgr<EditorManager>::instance = 0;

    EditorManager::EditorManager()
    {
        m_notebookEditor = new NotebookEditor( Manager::GetMainFrame(), ID_NOTEBOOKEDITOR );
    }

    EditorManager::~EditorManager()
    {

    }


    int EditorManager::FindEditor( const wxString &fileName ) const
    {
        for( size_t i=0; i<m_notebookEditor->GetPageCount(); ++i )
        {
            if( static_cast<sdk::Editor *>( m_notebookEditor->GetPage( i ) )->GetFileName() == fileName )
                return i;
        }

        return -1;
    }

    bool EditorManager::SaveEditorAs()
    {
         wxFileDialog dlg( Manager::GetMainFrame(), wxT( "Save file as..." ), wxT( "" ), wxT( "" ), wxT( "*" ), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

        int res = dlg.ShowModal();

        if( res != wxID_OK )
            return false;

        sdk::Editor *editor = GetCurrentEditor();
        editor->SetReadOnly( false );
        const wxString fileName = dlg.GetPath();
        m_notebookEditor->SetPageText( m_notebookEditor->GetPageIndex( editor ), wxT( '*' ) + fileName.AfterLast( wxT( '/' ) ) );
        editor->SetLexer( sdk::LexerManager::Get()->GetLexerByFileMask( fileName.AfterLast( '.' ) ) );
        editor->LoadSettings();
        editor->SetFileName( fileName );
        editor->SaveFile( fileName );

        return true;
    }

    bool EditorManager::SaveCurrentEditor()
    {
        return SaveEditor( GetCurrentEditor() );
    }

    bool EditorManager::SaveAllEditors()
    {
        for( size_t i=0; i<m_notebookEditor->GetPageCount(); ++i )
            if( !SaveEditor( static_cast<sdk::Editor *>( m_notebookEditor->GetPage( i ) ) ) )
                return false;

        return true;
    }

    bool EditorManager::SaveEditor( const wxString &fileName )
    {
        const int index = FindEditor( fileName );

        if( index != -1 )
            return SaveEditor( dynamic_cast<sdk::Editor *>( m_notebookEditor->GetPage( index ) ) );

        return true;
    }

    bool EditorManager::SaveEditor( sdk::Editor *editor )
    {
        if( editor->GetModify() )
        {
            wxString fileName = editor->GetFileName();

            if( fileName == wxEmptyString )
            {
                m_notebookEditor->SetSelection( m_notebookEditor->GetPageIndex( editor ) );

                wxFileDialog dlg( Manager::GetMainFrame(), wxT( "Save file..." ), wxT( "" ), wxT( "" ), wxT( "*" ), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

                int res = dlg.ShowModal();

                if( res != wxID_OK )
                    return false;

                fileName = dlg.GetPath();
                m_notebookEditor->SetPageText( m_notebookEditor->GetPageIndex( editor ), wxT( '*' ) + fileName.AfterLast( wxT( '/' ) ) );
                editor->SetLexer( sdk::LexerManager::Get()->GetLexerByFileMask( fileName.AfterLast( '.' ) ) );
                editor->LoadSettings();
                editor->SetFileName( fileName );
            }

            if( sdk::ConfigManager::Get()->GetFile( sdk::Editor::s_fileConfig )->ReadBool( wxT( "/config/general/eofoptions/striptb" ), true ) )
                    editor->StripTrailingSpaces();

            if( sdk::ConfigManager::Get()->GetFile( sdk::Editor::s_fileConfig )->ReadBool( wxT( "/config/general/eofoptions/endwithbl" ), true ) )
            {
                wxString lastLine( editor->GetLine( editor->GetLineCount()-1 ) );
                if( lastLine.Trim() != wxEmptyString )
                    editor->AppendText( wxT( "\n" ) );
            }

            editor->SaveFile( fileName );
        }

        return true;
    }


    bool EditorManager::CloseCurrentEditor()
    {
        return CloseEditor( GetCurrentEditor() );
    }

    bool EditorManager::CloseAllEditors()
    {
        const size_t pages = m_notebookEditor->GetPageCount();
        for( size_t i=0; i<pages; ++i )
            if( !CloseEditor( dynamic_cast<sdk::Editor *>( m_notebookEditor->GetPage( 0 ) ) ) )
                return false;

        return true;
    }

    bool EditorManager::CloseEditor( const wxString &fileName )
    {
        const int index = FindEditor( fileName );

        if( index != -1 )
            return CloseEditor( dynamic_cast<sdk::Editor *>( m_notebookEditor->GetPage( index ) ) );

        return true;
    }

    bool EditorManager::CloseEditor( sdk::Editor *editor )
    {
        const size_t index = m_notebookEditor->GetPageIndex( editor );

        if( editor->GetModify() )
        {
            const int res = wxMessageBox( wxT( "File " ) + editor->GetFileName() +
                wxT( " is modified... Do you want to save the changes?" ), wxT( "Close file" ), wxYES_NO | wxCANCEL );

            if( res == wxCANCEL )
            {
                return false;
            }
            if( res == wxYES )
            {
                if( !SaveEditor( editor ) )
                {
                    return false;
                }
            }
        }

        m_notebookEditor->DeletePage( index );

        if( m_notebookEditor->GetPageCount() == 0 )
        {
            wxStatusBar *sbar = Manager::GetMainFrame()->GetStatusBar();
            sbar->SetStatusText( wxT( "Welcome to IDEALL" ), 0 );
            sbar->SetStatusText( wxEmptyString, 1 );
            sbar->SetStatusText( wxEmptyString, 2 );
            sbar->SetStatusText( wxEmptyString, 3 );
            sbar->SetStatusText( wxEmptyString, 4 );
            sbar->SetStatusText( wxEmptyString, 5 );
        }

        return true;
    }

    sdk::Editor *EditorManager::GetCurrentEditor() const
    {
        return dynamic_cast<sdk::Editor *>( m_notebookEditor->GetPage( m_notebookEditor->GetSelection() ) );
    }

    sdk::Editor *EditorManager::GetEditor( const wxString &fileName ) const
    {
        int index = FindEditor( fileName );
        if( index != -1 )
            return dynamic_cast<sdk::Editor *>( m_notebookEditor->GetPage( index ) );

        return NULL;
    }

    void EditorManager::OpenFile( const wxString &fileName, const wxString &title, const wxBitmap &image )
    {
        int index = FindEditor( fileName );
        if( index != -1 )
            m_notebookEditor->SetSelection( index );

        else
        {
            sdk::Editor *se = new sdk::Editor( m_notebookEditor, wxID_ANY );
            se->SetFileName( fileName );
            se->LoadFile( fileName );
            se->SetLexer( sdk::LexerManager::Get()->GetLexerByFileMask( fileName.AfterLast( '.' ) ) );
            se->LoadSettings();
            se->SetSavePoint();

    //        struct stat fileStat;
    //        if( stat( fileName.char_str(), &fileStat) > -1 )
    //            if( fileStat.st_uid != 0 || !(fileStat.st_mode & S_IWUSR) );
    //                se->SetReadOnly( true );
            /** REVISAR SI EL ARCHIVO PUEDE SER MODIFICADO PARA VOLVERLO EDITABLE O NO EDITABLE**/

            if( title != wxEmptyString )
                m_notebookEditor->AddPage( se, title, true, image );
            else
                m_notebookEditor->AddPage( se, fileName.AfterLast( wxT( '/' ) ), true, image );
        }
    }

    void EditorManager::NewFile()
    {
        sdk::Editor *se = new sdk::Editor( m_notebookEditor, wxID_ANY );
        se->LoadSettings();
        m_notebookEditor->AddPage( se, wxT( "Untitled" ), true );
    }

    int EditorManager::SetSelectionEditor( const wxString &fileName )
    {
        int index = FindEditor( fileName );

        if( index != -1 )
            m_notebookEditor->SetSelection( index );

        return index;
    }

    NotebookEditor *EditorManager::GetNotebookEditor() const
    {
        return m_notebookEditor;
    }
}




